TOOL.Category	= "Construction"
TOOL.Name		= "#Smart Constraint"
TOOL.Command	= nil
TOOL.ConfigName = ""

TOOL.ClientConVar["weld"] = 0
TOOL.ClientConVar["weld_max"] = "1"
TOOL.ClientConVar["nocollide"] = 0
TOOL.ClientConVar["nocollide_max"] = "1"
TOOL.ClientConVar["unfreeze"] = 0

if(CLIENT) then
	language.Add("Tool_smart_constraint_name", "Smart Constraint")
	language.Add("Tool_smart_constraint_desc", "Weld / Nocollide Props Easily")
	language.Add("Tool_smart_constraint_0", "Left click selects/deselects a prop. Right click smart constraints the prop.")
	language.Add("Undone_smart_constraint", "Undone Smart Constraint")	
end

function TOOL:ClearSelectedProps()
	if(!self.SelectedProps) then return false end
	if(table.Count(self.SelectedProps) > 0) then
		for k, v in pairs(self.SelectedProps) do
			if(v.ent:IsValid()) then
				v.ent:SetColor(v.r, v.g, v.b, v.a)
			end
		end
		self.SelectedProps = {}
		return true
	else
		return false
	end
end

function TOOL:SmartGetAllEntities(Entity, MainEntTable, MainConstraintTable)
	local MainEntTable = MainEntTable || {}
	local MainConstraintTable = MainConstraintTable || {}
	if(!Entity:IsValid()) then return end
	if(!table.HasValue(MainEntTable, Entity)) then
		table.insert(MainEntTable, Entity)
	end
	if(!constraint.HasConstraints(Entity)) then return MainEntTable end
	for k, Constraint in pairs(Entity.Constraints) do
		if(!table.HasValue(MainConstraintTable, Constraint)) then
			table.insert(MainConstraintTable, Constraint)
			if(Constraint["Ent"] && Constraint["Ent"]:IsValid()) then
				SmartGetAllEntities(Constraint["Ent"].Entity, MainEntTable, MainConstraintTable)
			else
				for i=1, 6 do
					if(Constraint["Ent"..i] && Constraint["Ent"..i]:IsValid()) then
						SmartGetAllEntities(Constraint["Ent"..i].Entity, MainEntTable, MainConstraintTable)
					end
				end
			end
		end
	end
	--return MainEntTable, MainConstraintTable
	return MainEntTable
end

function TOOL:SmartConstraint(MainEntTable, Weld, MaxWelds, Nocollide, MaxNocollides, Unfreeze)	
	local StartTime = CurTime()
	if(Weld) then
		local WeldedPropsTotal = 0
		local WeldProps = {}
		for k0,v0 in pairs(MainEntTable) do
			WeldProps[k0] = {}
		end
		for k1,v1 in pairs(MainEntTable) do
			for x=1, MaxWelds do
				Msg("For\n")
				local ClosestDistance = 99999999
				local ClosestProp = false
				for k2,v2 in pairs(MainEntTable) do
					Msg("k2-v2\n")
					if(k1 != k2) then
						Msg("k1 != l2\n")
						local Check = false
						for k3,v3 in pairs(WeldProps[k1]) do
							if(v3.ent == k2) then
								Check = true
								Msg("Check=1\n")
								break
							end
						end
						if(!Check) then
							Msg("!Check\n")
							local Distance = (v1.ent:GetPos() - v2.ent:GetPos()):Length()
							if(Distance < 999999999) then
								ClosestDistance = Distance
								ClosestProp = v2.ent
								Msg("Closest'D\n")
							end
						end
					end
				end
				if(ClosestProp != false) then
					local WeldConstraint = constraint.Weld(v1.ent, ClosestProp, 0, 0, 0)
					Msg("Welded\n")
				    undo.AddEntity(WeldConstraint)
					WeldedPropsTotal = WeldedPropsTotal+1
					table.insert(WeldProps[k1], ClosestProp)
					table.insert(WeldProps[ClosestProp], k1)
				else
					Msg("Already Welded\n")
					break
				end
			end
		end
	end
	
	-- for k1,v1 in pairs(MainEntTable) do
		-- for k2,v2 in pairs(MainEntTable) do		
			-- if(Nocollide) then
				-- if(k1 != k2) then
					-- local Check = false
					-- for i, val in ipairs(welds[a]) do
						-- if(val==b) then
							-- linked=true
							-- break
						-- end
					-- end

					-- if(!Linked) then
						-- local distance = (v:GetPos()-w:GetPos()):Length()
						-- if(distance < nocollideradius) then
							-- local CNocollide = constraint.NoCollide(v, w, 0, 0)
							-- Undo.AddEntity(CNocollide)
						-- end
					-- end
				-- end
			-- end
		-- end
	-- end
	if(Unfreeze) then
		for k3,v3 in pairs(MainEntTable) do	
			v3.ent:GetPhysicsObject():EnableMotion(true)
		end
		Msg("Unfreeze'D\n")
	end
	-- if(Weld) then
		-- local entweld = constraint.Weld(lastent, newent, 0, 0, 0 )
	-- end
	self:ClearSelectedProps()
end

function TOOL:SelectEnt(ent)
	local Prop = {}
	Prop.ent = ent
	Prop.r, Prop.g, Prop.b, Prop.a = ent:GetColor()
	table.insert(self.SelectedProps, Prop)
	ent:SetColor(0, 255, 0, 255)
end

function TOOL:CheckEnt(ent)
	local FoundIt = false
	if(table.Count(self.SelectedProps) == 0) then
		return false
	end
	for k, Prop in pairs(self.SelectedProps) do
		if(Prop.ent == ent) then
			FoundIt = true
		end
	end
	if(FoundIt == true) then
		return true
	else
		return false
	end
end

function TOOL:LeftClick(tr)
	if(!tr.Entity || !tr.Entity:IsValid() || tr.Entity:IsPlayer() || tr.Entity:IsWorld()) then return false end
	if(CLIENT) then return true end
	
	local ply = self:GetOwner()
	local ent = tr.Entity
	
	if(!self.SelectedProps) then
		self.SelectedProps = {}
	end
	
	if(ply:KeyDown(IN_SPEED)) then
		local SelectedProps = 0
		local SmartTable = SmartGetAllEntities(ent)
		for k,v in pairs(SmartTable) do
			if(v:IsValid() && !self:CheckEnt(v)) then
				self:SelectEnt(v)
				SelectedProps = SelectedProps+1
			end
		end
		self:GetOwner():PrintMessage(HUD_PRINTTALK, "Smart Constraint: "..SelectedProps.." props were selected.")
	elseif(self:CheckEnt(ent)) then
		for k, Prop in pairs(self.SelectedProps) do
			if(Prop.ent == ent) then
				Prop.ent:SetColor(Prop.r, Prop.g, Prop.b, Prop.a)
				table.remove(self.SelectedProps, k)
			end
		end
	else
		self:SelectEnt(ent)
	end
	
	return true
end

function TOOL:RightClick(tr)
	if(CLIENT) then return true end
	local ply = self:GetOwner()
	local ent = tr.Entity
	
	local weld	= self:GetClientNumber("weld")
	local weld_max	= self:GetClientNumber("weld_max")
	local nocollide	= self:GetClientNumber("nocollide")
	local nocollide_max	= self:GetClientNumber("nocollide_max")
	local unfreeze	= self:GetClientNumber("unfreeze")

	if(!weld && !nocollide && !unfreeze || table.Count(self.SelectedProps) <= 1) then return false end
	self:GetOwner():PrintMessage(HUD_PRINTTALK, "Smart Constraint: Constraining...")
	
	undo.Create("smart_constraint")	
	self:SmartConstraint(self.SelectedProps, weld, weld_max, nocollide, nocollide_max, unfreeze)	
	undo.SetPlayer(ply)
	undo.Finish()
	
	self:GetOwner():PrintMessage(HUD_PRINTTALK, "Smart Constraint: Finished.")
	return true
end

function TOOL:Reload(tr)
	if(CLIENT) then return true end
	self:ClearSelectedProps()
end

function TOOL.BuildCPanel(CPanel)
	CPanel:AddControl("Header", {Text = "Smart Constraint By Spacetech"})
    CPanel:AddControl("CheckBox", {Label = "Weld", Command = "smart_constraint_weld"})
    CPanel:AddControl("Slider", {Label = "Welds Per Prop:", Type = "integer", Min = "1", Max = "10", Command = "smart_constraint_weld_max" } )
    CPanel:AddControl("CheckBox", {Label = "Nocollide", Command = "smart_constraint_nocollide"})
	CPanel:AddControl("Slider", {Label = "Nocollides Per Prop:", Type = "integer", Min = "1", Max = "10", Command = "smart_constraint_nocollide_max" } )	
    CPanel:AddControl("CheckBox", {Label = "Unfreeze", Command = "smart_constraint_unfreeze"})
end
